package edu.miami.group.photolog;

import java.io.File;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Images;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

public class ViewPhlog extends Activity {
	private static final int ACTIVITY_SEND_EMAIL = 0;
	private static final int ACTIVITY_EDIT_PHLOG = 1;
	ContentValues databaseObject;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		
		
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_view_phlog);
		
		databaseObject = this.getIntent().getParcelableExtra("databaseObject");
		populateFields(databaseObject);
		
	}
	
	/**
	 * Use BitmapFactory to decode a byte array (blob) and return it as a Bitmap
	 * @param bArray bitmap stored as blob
	 * @return useable bitmap
	 */
	public static Bitmap decodeBlob(byte[] bArray) {
		return BitmapFactory.decodeByteArray(bArray, 0, bArray.length);
	}
	
	/**
	 * Take latitude / longitude coordinates in double form and creates a
	 * suitable display string
	 * @param latitude latitude double value
	 * @param longitude latitude double value
	 * @return Formatted string
	 */
	public static String formatLatLong(double latitude, double longitude) {
		DecimalFormat df = new DecimalFormat("#.##");
		StringBuilder coords = new StringBuilder(df.format(Math.abs(latitude)));
		if (latitude > 0) coords.append(" N / " + df.format(Math.abs(longitude)));
		else coords.append(" S / " + df.format(Math.abs(longitude)));
		if (longitude > 0) coords.append(" E");
		else coords.append(" W");
		return coords.toString();
	}
	
	/**
	 * Takes timeinmillis and converts it to a usable date string
	 * @param milliTime time in millis
	 * @return formatted date/time string
	 */
	public static String formatDate(long milliTime) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(milliTime);
		SimpleDateFormat format = new SimpleDateFormat("MMM d yyyy, H:mm", Locale.US);
		return format.format(calendar.getTime());
	}

	/**
	 * Populate the fields of the view activity 
	 * @param databaseObject ContentValues from a PhlogBase entry
	 */
	private void populateFields(ContentValues databaseObject) {
		TextView tv_title, tv_date, tv_location, tv_geo;
		EditText et_description;
		ImageView iv_picture;
		
		// Find all the views
		tv_title = (TextView) findViewById(R.id.view_title);
		tv_date = (TextView) findViewById(R.id.view_date);
		tv_location = (TextView) findViewById(R.id.view_location);
		tv_geo = (TextView) findViewById(R.id.view_geo);
		et_description = (EditText) findViewById(R.id.view_description);
		iv_picture = (ImageView) findViewById(R.id.view_picture);
		
		// Set the easy ones first
		tv_title.setText(databaseObject.getAsString("title"));
		et_description.setText(databaseObject.getAsString("description"));
		
		// Get, decode, and post the bitmap blob
		iv_picture.setImageBitmap(decodeBlob(databaseObject.getAsByteArray("picVid")));
		
		// Grab Lat / Long, format, and post
		double latitude = databaseObject.getAsDouble("latitude");
		double longitude = databaseObject.getAsDouble("longitude");
		tv_location.setText(formatLatLong(latitude, longitude));
		
		// Geocode the coordinates and post
		String geocodedLocation = androidGeodecode(latitude, longitude);
		Log.i("IN populateFields", "Location reported: " + geocodedLocation);
		tv_geo.setText(geocodedLocation);
		
		// Grab post date, format, and post
		String datetime = formatDate(databaseObject.getAsLong("date"));
		tv_date.setText(datetime);

		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_view_phlog, menu);
		return true;
	}
	
	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()) {
		case R.id.menu_email:
			// Prepare elements for email.
			Bitmap bmToSend = decodeBlob(databaseObject.getAsByteArray("picVid"));
			String path = Images.Media.insertImage(getContentResolver(), bmToSend, "title", null);
			Uri bmUri = Uri.parse(path);
			StringBuilder subject = new StringBuilder(databaseObject.getAsString("title"));
			subject.append(" - " + formatDate(databaseObject.getAsLong("date")));
			
			Intent emailIntent = new Intent(Intent.ACTION_SEND);
			emailIntent.setType("image/*");
			emailIntent.putExtra(Intent.EXTRA_STREAM, bmUri);
			emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject.toString());
			emailIntent.putExtra(Intent.EXTRA_TEXT, databaseObject.getAsString("description"));
			startActivityForResult(Intent.createChooser(emailIntent, "Choose a method..."), ACTIVITY_SEND_EMAIL);
			return true;
		case R.id.menu_edit:
			Intent editIntent = new Intent();
			editIntent.setClassName("edu.miami.group.photolog", "edu.miami.group.photolog.CreatePhlog");
			editIntent.putExtra("databaseObject", databaseObject);
			editIntent.putExtra(Login.TABLE_NAME, getIntent().getStringExtra(Login.TABLE_NAME));
			startActivityForResult(editIntent, ACTIVITY_EDIT_PHLOG);
			return true;
		default:
			return(super.onOptionsItemSelected(item));
		}
	}
	
	@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode,resultCode,data);
		
		switch(requestCode) {
		case ACTIVITY_EDIT_PHLOG:
			if (resultCode == RESULT_OK) {
				databaseObject = data.getParcelableExtra("databaseObject");
				populateFields(databaseObject);
				break;
			} else break;
		case ACTIVITY_SEND_EMAIL:
			break;
		default:
			break;
		}
	}
	
	/**
	 * Modified geoCoder taken from notes to accept long/lat rather than
	 * a Location object
	 * @param latitude
	 * @param longitude
	 * @return formatted location String or 'Unknown Location' for errors (logged).
	 */
	private String androidGeodecode(double latitude, double longitude) {
		StringBuilder outString;
		Geocoder androidGeocoder;
		List<Address> addresses;
		Address firstAddress;
		String addressLine;
		
		if (Geocoder.isPresent()) {
			androidGeocoder = new Geocoder(this);
			try {
				addresses = androidGeocoder.getFromLocation(latitude, longitude, 1);
				if (addresses.isEmpty()) {
					Log.e("IN androidGeodecode", "addresses is empty");
					return "Unknown Location";
				}
				else {
					firstAddress = addresses.get(0);
					outString = new StringBuilder();
					for (int i = 0; (addressLine = firstAddress.getAddressLine(i)) != null; i++) {
						outString.append(addressLine);
						outString.append(", ");
					}
					// Clean up the last comma
					outString.delete(outString.length()-2, outString.length()-1);
					return outString.toString();
				} 					
			} catch (Exception ex) {
				Log.e("IN androidGeodecode", "Error: " + ex.getMessage());
				return "Unknown Location";
			}
		} else {
			Log.e("IN androidGeodecode", "No Geodecoder present!");
			return "Unknown Location";
		}
	}

}